package serverManager;

import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import os_listener.ServerUpdates;
import db_manager.Dir;
import db_manager.Manager;

/**
 * this class send a new update to the user through a socket connection
 */
public class UpdatesManager extends Thread
{
	ServerSocket serverSocket=null;
	Socket clientSocket=null;
	ServerUpdates su;
	
	/**
	 * this function is the constructor of this class
	 * @param su - the new update to send to the user
	 * @throws IOException
	 */
	public UpdatesManager(ServerUpdates su) throws IOException
	{
		this.su = su;
		// start listen to port 7777
		serverSocket = new ServerSocket(7777);
	}

	/**
	 * this function performs the main action of this class - updating the user with a new update
	 */
	public void run()
	{
		try
		{
			clientSocket=serverSocket.accept();
			ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
			// the case that the update is sharing a folder with this user
			if(su.getUpdate().equals("sharing folder"))
			{
				// sending the update
				out.writeObject(su);
				String hash, file_name;
				Manager manager = Manager.getInstance();
				File sessionFile = new File("C:\\Program Files\\m&l_dropbox_server\\hibernate.cfg.xml");
				SessionFactory sessionFactory = new Configuration().configure(sessionFile).buildSessionFactory();
				// creating a new session
				Session session = sessionFactory.openSession();
				// get the details of the dir that was shared
				Dir dir = manager.findDir(session, su.getDir_name(), su.getOld_user_name());
				long dir_id = dir.getDir_id();
				// a list of the file names in the shared dir
				ArrayList<String> file_names = new ArrayList<String>();
				// a list of the hashes of the files in the shared dir
				ArrayList<String> hashes = manager.findHashesInDir(session, dir_id, file_names);
				// for each file in the shared dir
				for (int i = 0; i < hashes.size(); i++) 
				{
					hash = hashes.get(i);
					file_name = file_names.get(i);
					byte[] bytes = manager.findFileFromUploadServerFiles(hash);
					// the case that the file was found in the server files
					if(bytes != null)
					{
						su.setBytes(bytes);
						su.setFile_name(file_name);
						su.setUpdate("recover file from dir");
						out = new ObjectOutputStream(clientSocket.getOutputStream());
						// sending the update
						out.writeObject(su);
					}
				}
				session.flush();
			}
			// the case that the update is a new file in a shared dir of this user
			if(su.getUpdate().equals("new file in shared folder"))
			{
				Manager manager = Manager.getInstance();
				byte[] bytes = manager.findFileFromUploadServerFiles(su.getHash());
				// the case that the file was found in the server files
				if(bytes != null)
				{
					su.setBytes(bytes);
					// sending the update
					out.writeObject(su);
				}
			}
			// the case that the new update is deletd file from a shared dir of this user
			if(su.getUpdate().equals("delete file from shared folder"))
			{
				// sending the update
				out.writeObject(su);
			}
			su.setBytes(null);
			su.setUpdate("the end");
			out = new ObjectOutputStream(clientSocket.getOutputStream());
			// sending a massage of the end of this update to the user
			out.writeObject(su);
			// the case that the socket needs to be closed
			if (clientSocket != null)
			{
				clientSocket.close();
			}
			// the case that the server socket needs to be closed
			if (serverSocket != null) 
			{
				serverSocket.close();
			}
		}
		catch(Exception e)
		{
			return;
		}
	}
}
